package kafka

import (
	"context"
	"crypto/tls"
	"errors"
	"time"

	kfkgo "github.com/segmentio/kafka-go"
)

type Payload struct {
	Key        []byte
	Value      []byte
	Headers    []kfkgo.Header
	WriterData any
}

func (c *client) WriteMessages(ctx context.Context, payloads ...*Payload) error {
	if len(payloads) == 0 {
		return nil
	}

	times := 0
Retry:
	if c.writer == nil {
		c.Lock()
		c.writer = &kfkgo.Writer{
			Addr:         kfkgo.TCP(c.address),
			Topic:        c.topic,
			Balancer:     &kfkgo.Hash{},
			WriteTimeout: 0,
			RequiredAcks: 0,
			Async:        false,
			Transport: &kfkgo.Transport{
				DialTimeout: 30 * time.Second,
				TLS:         &tls.Config{InsecureSkipVerify: true}, // todo
				SASL:        c.mechanism,
				Context:     c.ctx,
			},
			AllowAutoTopicCreation: true,
		}
		c.Unlock()
	}

	now := time.Now()

	msgs := make([]kfkgo.Message, 0, len(payloads))

	for _, item := range payloads {
		msgs = append(msgs, kfkgo.Message{
			Key:        item.Key,
			Value:      item.Value,
			Headers:    item.Headers,
			WriterData: item.WriterData,
			Time:       now,
		})
	}

	context.WithoutCancel(ctx)
	if err := c.writer.WriteMessages(ctx, msgs...); err != nil {
		if errors.Is(err, context.DeadlineExceeded) {
			goto HandleError
		}

		if c.reconnection {
			times++
			c.logger.Warn("kafka.WriteMessage: reconnection after 30 seconds, times = %d, err = %s", times, err.Error())
			time.Sleep(30 * time.Second)
			c.Lock()
			c.writer = nil
			c.Unlock()
			goto Retry
		}

	HandleError:
		c.logger.Warn("kafka.WriteMessage: err = %s", err.Error())
		return err
	}

	return nil
}
